package com.isi.mtl.lf.jag;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import com.isi.mtl.lf.jag.constantes.Units;
import com.isi.mtl.lf.jag.entities.Bounds;
import com.isi.mtl.lf.jag.entities.Coord;
import com.isi.mtl.lf.jag.entities.Distance;
import com.isi.mtl.lf.jag.entities.Duration;
import com.isi.mtl.lf.jag.entities.Leg;
import com.isi.mtl.lf.jag.entities.Overview_Polyline;
import com.isi.mtl.lf.jag.entities.Route;
import com.isi.mtl.lf.jag.entities.Step;
import com.isi.mtl.lf.jag.exceptions.OVER_QUERY_LIMIT_Exception;
import com.isi.mtl.lf.jag.exceptions.REQUEST_DENIED_Exception;
import com.isi.mtl.lf.jag.exceptions.ZERO_RESULTS_Exception;
import com.isi.mtl.lf.jag.parameters.AutoCompleteParameter;
import com.isi.mtl.lf.jag.parameters.DirectionParameter;
import com.isi.mtl.lf.jag.parameters.Parameter;

/***
 * 
 * @author Loic FALKLAND
 * @version 1.0
 * 
 */


public class JAG {

	/***
	 * 
	 * @param parameter representation of the Google Map's Web Services' request
	 * @return String value depending the Unit constant provides
	 * @throws ZERO_RESULTS_Exception That exception from by the fact of the Google Map's Webservice's reponse.<br />Meaning that the service couldn't operate due to user input.
	 * 
	 */
	public String getMetricDistanceBeetween(Parameter parameter){
		
		String distance = null;
		String unit = null;
		boolean flag = true;

			if(parameter.getMetric() == Units.IMPERIAL || parameter.getMetric() == Units.METRIC){
				
				if(parameter.getMetric() == Units.METRIC){
					unit = "metric";
				}
				
				if(parameter.getMetric() == Units.IMPERIAL){
					unit = "imperial";
				}

			}
			else {
				flag = false;
			}


			if(flag){
				
				String from = parameter.getFrom();
				String to = parameter.getTo();
				String addressToConnect = null;
				
				try {
					
					//Formattage des strings pour le passage en URL
					from = URLEncoder.encode(from, "UTF-8");
					to = URLEncoder.encode(to, "UTF-8");
					if(parameter.getSecure_transaction()){
						addressToConnect = "https://maps.googleapis.com/maps/api/distancematrix/xml?origins="+from+"&destinations="+to+"&mode=driving&units="+unit+"&sensor="+parameter.getSensor();
					}
					else {
						addressToConnect = "http://maps.googleapis.com/maps/api/distancematrix/xml?origins="+from+"&destinations="+to+"&mode=driving&units="+unit+"&sensor="+parameter.getSensor();
					}
					
					
					//Partie connexion
					URL url = new URL(addressToConnect);
					HttpURLConnection connexion = (HttpURLConnection) url.openConnection();
					connexion.connect();
					InputSource geocoderResultInputSource;
					geocoderResultInputSource = new InputSource(connexion.getInputStream());
					
					//Partie XML/XPATH
					
					Document geocoderResultDocument = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(geocoderResultInputSource);
					XPath xpath = XPathFactory.newInstance().newXPath();
					
					//On s'assure que la requete envoy�e � l'API � bien renvoy�e un STATUS = OK cf. Google API
					NodeList nodeListCodeResult = (NodeList) xpath.evaluate("//status", geocoderResultDocument, XPathConstants.NODESET);
					
					if(nodeListCodeResult.item(0).getTextContent().equals("OK")){
						
					    NodeList resultNodeList = (NodeList) xpath.evaluate("//distance[position() = 1]/text", geocoderResultDocument, XPathConstants.NODESET);

					    //On s'assure bien qu'un r�sultat est bien retourn�
					    if(resultNodeList.getLength() == 1) {
					    	distance = String.valueOf(resultNodeList.item(0).getTextContent());
					    }
						
					}
					else {
						throw new ZERO_RESULTS_Exception(ZERO_RESULTS_Exception.defaultMessage);
					}

				} catch (UnsupportedEncodingException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (MalformedURLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (SAXException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (ParserConfigurationException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (XPathExpressionException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (ZERO_RESULTS_Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}

			}

		return distance;
		
	}
	
	
	/***
	 * 
	 * @param parameter representation of the Google Map's Web Services' request
	 * @return Double the distance in meters
	 * @throws ZERO_RESULTS_Exception That exception from by the fact of the Google Map's Webservice's reponse.<br />Meaning that the service couldn't operate due to user input.
	 */
	public Double distanceBeetween(Parameter parameter){
		
		Double distance = null;

		String from = parameter.getFrom();
		String to = parameter.getTo();
		String addressToConnect = null;
			
			try {
				
				//Formattage des strings pour le passage en URL
				from = URLEncoder.encode(from, "UTF-8");
				to = URLEncoder.encode(to, "UTF-8");
				
				if(parameter.getSecure_transaction()){
					addressToConnect = "https://maps.googleapis.com/maps/api/distancematrix/xml?origins="+from+"&destinations="+to+"&mode=driving&sensor="+parameter.getSensor();
				}
				else {
					addressToConnect = "http://maps.googleapis.com/maps/api/distancematrix/xml?origins="+from+"&destinations="+to+"&mode=driving&sensor="+parameter.getSensor();
				}
				
				//Partie connexion
				URL url = new URL(addressToConnect);
				HttpURLConnection connexion = (HttpURLConnection) url.openConnection();
				connexion.connect();
				InputSource geocoderResultInputSource;
				geocoderResultInputSource = new InputSource(connexion.getInputStream());
				
				//Partie XML/XPATH
				
				Document geocoderResultDocument = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(geocoderResultInputSource);
				XPath xpath = XPathFactory.newInstance().newXPath();
				
				//On s'assure que la requete envoy�e � l'API � bien renvoy�e un STATUS = OK cf. Google API
				NodeList nodeListCodeResult = (NodeList) xpath.evaluate("//status", geocoderResultDocument, XPathConstants.NODESET);
				
				if(nodeListCodeResult.item(0).getTextContent().equals("OK")){
					
				    NodeList resultNodeList = (NodeList) xpath.evaluate("//distance[position() = 1]/value", geocoderResultDocument, XPathConstants.NODESET);

				    //On s'assure bien qu'un r�sultat est bien retourn�
				    if(resultNodeList.getLength() == 1) {
				    	distance = Double.parseDouble(resultNodeList.item(0).getTextContent());
				    }
					
				}
				else {
					throw new ZERO_RESULTS_Exception(ZERO_RESULTS_Exception.defaultMessage);
				}

			} catch (UnsupportedEncodingException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (MalformedURLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (SAXException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (ParserConfigurationException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (XPathExpressionException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (ZERO_RESULTS_Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			

		return distance;
		
	}
	
	
	/***
	 * 
	 * @param autoCompleteParameter Java object representation of the request
	 * @return ArrayList<String> values of matched citie's names
	 * @throws ZERO_RESULTS_Exception That exception from by the fact of the Google Map's Webservice's reponse.<br />Meaning that the service couldn't operate due to user input.
	 * @throws REQUEST_DENIED_Exception Indicates that the service denied use of the directions service by your application. API Key may be sometimes the clue ;)
	 * @throws OVER_QUERY_LIMIT_Exception Indicates that you are over your quota.
	 * 
	 */
	public ArrayList<String> getCities(AutoCompleteParameter autoCompleteParameter){

		ArrayList<String> alCities = new ArrayList<>();
		
		//Formattage string pour l'url
		
		try {
			
			String input = URLEncoder.encode(autoCompleteParameter.getInput(), "UTF-8");
			String addressToConnect = null;
			String languageRetrieved = autoCompleteParameter.getLanguageMapping().get(autoCompleteParameter.getLanguage());
			
			if(autoCompleteParameter.getSecure_transaction()){
				addressToConnect = "https://maps.googleapis.com/maps/api/place/autocomplete/xml?input="+input+"&types=geocode&language="+languageRetrieved+"&sensor="+autoCompleteParameter.getSensor()+"&key="+autoCompleteParameter.getAPI_Key();
			}
			else {
				addressToConnect = "http://maps.googleapis.com/maps/api/place/autocomplete/xml?input="+input+"&types=geocode&language="+languageRetrieved+"&sensor="+autoCompleteParameter.getSensor()+"&key="+autoCompleteParameter.getAPI_Key();
			}
			
			//Partie connexion
			URL url = new URL(addressToConnect);
			HttpURLConnection connexion = (HttpURLConnection) url.openConnection();
			connexion.connect();
			InputSource geocoderResultInputSource;
			geocoderResultInputSource = new InputSource(connexion.getInputStream());
			
			//Partie XML/XPATH
			Document geocoderResultDocument = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(geocoderResultInputSource);
			XPath xpath = XPathFactory.newInstance().newXPath();
			
			//On s'assure que la requete envoy�e � l'API � bien renvoy�e un STATUS = OK cf. Google API
			NodeList nodeListCodeResult = (NodeList) xpath.evaluate("//status", geocoderResultDocument, XPathConstants.NODESET);
			
			String status_code = nodeListCodeResult.item(0).getTextContent();
			
			if(status_code.equals("OK")){
				
			    NodeList resultNodeList = (NodeList) xpath.evaluate("//prediction/description", geocoderResultDocument, XPathConstants.NODESET);
			    
			    //Ajout des villes retourn�es par l'API dans l'arraylist
			    for(int i=0; i<resultNodeList.getLength(); i++) {
			    	alCities.add(resultNodeList.item(i).getTextContent());
			    }

			}
			else if(status_code.equals("ZERO_RESULTS")) {
				throw new ZERO_RESULTS_Exception(ZERO_RESULTS_Exception.defaultMessage);
			}
			else if(status_code.equals("REQUEST_DENIED")){
				throw new REQUEST_DENIED_Exception(REQUEST_DENIED_Exception.defaultMessage);
			}
			else if(status_code.equals("OVER_QUERY_LIMIT")){
				throw new OVER_QUERY_LIMIT_Exception(OVER_QUERY_LIMIT_Exception.defaultMessage);
			}

		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (MalformedURLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SAXException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ParserConfigurationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (XPathExpressionException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ZERO_RESULTS_Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (REQUEST_DENIED_Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (OVER_QUERY_LIMIT_Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return alCities;
		
	}

	
	/***
	 * 
	 * @param directionParameter represents the data for the request to Google Map's Webservice
	 * @return Route representation of Google Map's Webservice response
	 * @throws ZERO_RESULTS_Exception That exception from by the fact of the Google Map's Webservice's reponse.<br />Meaning that the service couldn't operate due to user input.
	 * @throws REQUEST_DENIED_Exception Indicates that the service denied use of the directions service by your application. API Key may be sometimes the clue ;)
	 * @throws OVER_QUERY_LIMIT_Exception Indicates that you are over your quota.
	 */
	public Route getRoute(DirectionParameter directionParameter) {
		
		Route route = new Route();
		String from = null;
		String to = null;
		String travelModeRetrieved = null;
		String languageRetrieved = null;

		try{

			travelModeRetrieved = directionParameter.getTravelModeMapping().get(directionParameter.getTravel_Mode());
			languageRetrieved = directionParameter.getLanguageMapping().get(directionParameter.getLanguage());

			//Formattage des strings pour le passage en URL
			from = URLEncoder.encode(directionParameter.getFrom(), "UTF-8");
			to = URLEncoder.encode(directionParameter.getTo(), "UTF-8");
			String addressToConnect = null;
					
			//Url bati dynamiquement
			if(directionParameter.getSecure_transaction()){
				
				if(directionParameter.getWaypoints() == null){
					addressToConnect = "https://maps.googleapis.com/maps/api/directions/xml?origin="+from+"&destination="+to+"&sensor="+directionParameter.getSensor()+"&mode="+travelModeRetrieved+"&units="+directionParameter.getUnitChoosen()+"&language="+languageRetrieved;
				}
				else {
					addressToConnect = "https://maps.googleapis.com/maps/api/directions/xml?origin="+from+"&destination="+to+"&sensor="+directionParameter.getSensor()+"&mode="+travelModeRetrieved+"units="+directionParameter.getUnitChoosen()+"&waypoints=optimize:true|"+directionParameter.getFormattedWaypoints()+"&language="+languageRetrieved;
				}
				
			}
			else {
				
				if(directionParameter.getWaypoints() == null){
					addressToConnect = "http://maps.googleapis.com/maps/api/directions/xml?origin="+from+"&destination="+to+"&sensor="+directionParameter.getSensor()+"&units="+directionParameter.getUnitChoosen()+"&mode="+travelModeRetrieved+"&language="+languageRetrieved;
				}
				else {
					addressToConnect = "http://maps.googleapis.com/maps/api/directions/xml?origin="+from+"&destination="+to+"&sensor="+directionParameter.getSensor()+"&units="+directionParameter.getUnitChoosen()+"&mode="+travelModeRetrieved+"&waypoints=optimize:true|"+directionParameter.getFormattedWaypoints()+"&language="+languageRetrieved;
				}
				
			}
			
			System.out.println("***"+addressToConnect);
			
			//Partie connexion
			URL url = new URL(addressToConnect);
			HttpURLConnection connexion = (HttpURLConnection) url.openConnection();
			connexion.connect();
			InputSource geocoderResultInputSource;
			geocoderResultInputSource = new InputSource(connexion.getInputStream());
			
			//Partie XML/XPATH
			
			Document geocoderResultDocument = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(geocoderResultInputSource);
			XPath xpath = XPathFactory.newInstance().newXPath();
			
			//On s'assure que la requete envoy�e � l'API � bien renvoy�e un STATUS = OK cf. Google API
			NodeList nodeListCodeResult = (NodeList) xpath.evaluate("//status", geocoderResultDocument, XPathConstants.NODESET);
			
			String status_code = nodeListCodeResult.item(0).getTextContent();
			
			if(status_code.equals("OK")){
				
				System.out.println("ok");
				
				NodeList resultNodeList = null;
				
				//Setting summary
				resultNodeList = (NodeList) xpath.evaluate("//route/summary", geocoderResultDocument, XPathConstants.NODESET);
			    route.setSummary(resultNodeList.item(0).getTextContent());
			    
			    resultNodeList = (NodeList) xpath.evaluate("//leg/step", geocoderResultDocument, XPathConstants.NODESET);
			    String nodeName = null;
			    Step step = null;
			    Integer innerStartLocationLength = null;
			    Integer innerEndLocationLength = null;
			    
			    List<Step> listOfStep = new ArrayList<>();
			    
			    for(int i=0;i<resultNodeList.getLength();i++){
			    	
			    	NodeList stepNodes =  resultNodeList.item(i).getChildNodes();
			    	
			    	step = new Step();
			    	
			    	for(int j=0;j<stepNodes.getLength();j++){

			    		nodeName = stepNodes.item(j).getNodeName();
			    		
			    		if(nodeName.equals("travel_mode")){
			    			step.setTraval_mode(stepNodes.item(j).getTextContent());
			    		}
			       		if(nodeName.equals("start_location")){
			       			
			       			//Pour d�terminer s�par�ment lat et long
			       			innerStartLocationLength = stepNodes.item(j).getChildNodes().getLength();
			       			Coord coord = new Coord();
			       			for(int k=0;k<innerStartLocationLength;k++){

			       				if(stepNodes.item(j).getChildNodes().item(k).getNodeName().equals("lat")){
			       					coord.setLat(Double.valueOf(stepNodes.item(j).getChildNodes().item(k).getTextContent()));
			       				}
		
			       				if(stepNodes.item(j).getChildNodes().item(k).getNodeName().equals("lng")){
			       					coord.setLng(Double.valueOf(stepNodes.item(j).getChildNodes().item(k).getTextContent()));
			       				}

			       			}
			       			
			       			step.setStart_location(coord);
			       			
			    		}
			       		if(nodeName.equals("end_location")){
			       			
			       			//M�me chose :)
			       			Coord coord = new Coord();
			      			innerEndLocationLength = stepNodes.item(j).getChildNodes().getLength();
			       			for(int k=0;k<innerEndLocationLength;k++){

			       				if(stepNodes.item(j).getChildNodes().item(k).getNodeName().equals("lat")){
			       					coord.setLat(Double.valueOf(stepNodes.item(j).getChildNodes().item(k).getTextContent()));
			       				}
			       				if(stepNodes.item(j).getChildNodes().item(k).getNodeName().equals("lng")){
			       					coord.setLng(Double.valueOf(stepNodes.item(j).getChildNodes().item(k).getTextContent()));
			       				}

			       			}
			       			
			       			step.setEnd_location(coord);
		
			    		}
			       		if(nodeName.equals("polyline")){
			
			       			for(int k=0;k<stepNodes.item(j).getChildNodes().getLength();k++){

			       				if(stepNodes.item(j).getChildNodes().item(k).getNodeName().equals("points")){
			       					step.setPolyline(new Overview_Polyline(stepNodes.item(j).getChildNodes().item(k).getTextContent()));
			       				}

			       			}
			       			
			       		}
			       		if(nodeName.equals("duration")){
			       			
			       			Duration duration = new Duration();
			       			
			      			for(int k=0;k<stepNodes.item(j).getChildNodes().getLength();k++){

			       				if(stepNodes.item(j).getChildNodes().item(k).getNodeName().equals("value")){
			       					duration.setValue(Integer.parseInt(stepNodes.item(j).getChildNodes().item(k).getTextContent()));
			       				}
			       				if(stepNodes.item(j).getChildNodes().item(k).getNodeName().equals("text")){
			       					duration.setText(stepNodes.item(j).getChildNodes().item(k).getTextContent());
			       				}

			       			}
			      			
			      			step.setDuration(duration);
			       			
			       		}
			       		if(nodeName.equals("html_instructions")){
			       			step.setHtml_instructions(stepNodes.item(j).getTextContent());
			       		}
			       		if(nodeName.equals("distance")){
			       			
			       			Distance distance = new Distance();
			       			
			      			for(int k=0;k<stepNodes.item(j).getChildNodes().getLength();k++){

			       				if(stepNodes.item(j).getChildNodes().item(k).getNodeName().equals("value")){
			       					distance.setValue(Integer.parseInt(stepNodes.item(j).getChildNodes().item(k).getTextContent()));
			       				}
			       				if(stepNodes.item(j).getChildNodes().item(k).getNodeName().equals("text")){
			       					distance.setText(stepNodes.item(j).getChildNodes().item(k).getTextContent());
			       				}

			       			}
			       			
			       			step.setDistance(distance);
			       			
			       		}
			       		
			    	}

			    	
				    listOfStep.add(step);
			    	
			    }
			    
			    Leg leg = new Leg(listOfStep);
			    
			    Duration mainDuration = new Duration();
			    
			    resultNodeList = (NodeList) xpath.evaluate("//leg/duration/value", geocoderResultDocument, XPathConstants.NODESET);
			    mainDuration.setValue(Integer.parseInt(resultNodeList.item(0).getTextContent()));
			    resultNodeList = (NodeList) xpath.evaluate("//leg/duration/text", geocoderResultDocument, XPathConstants.NODESET);
			    mainDuration.setText(resultNodeList.item(0).getTextContent());
			    
			    leg.setMainDuration(mainDuration);
			    
			    Distance mainDistance = new Distance();
			    
			    resultNodeList = (NodeList) xpath.evaluate("//leg/distance/value", geocoderResultDocument, XPathConstants.NODESET);
			    mainDistance.setValue(Integer.parseInt(resultNodeList.item(0).getTextContent()));
			    resultNodeList = (NodeList) xpath.evaluate("//leg/distance/text", geocoderResultDocument, XPathConstants.NODESET);
			    mainDistance.setText(resultNodeList.item(0).getTextContent());
			    
			    leg.setMainDistance(mainDistance);
			    
			    Coord coord = new Coord();
			    
			    resultNodeList = (NodeList) xpath.evaluate("//leg/start_location/lat", geocoderResultDocument, XPathConstants.NODESET);
			    coord.setLat(Double.valueOf(resultNodeList.item(0).getTextContent()));
			    
			    resultNodeList = (NodeList) xpath.evaluate("//leg/start_location/lng", geocoderResultDocument, XPathConstants.NODESET);
			    coord.setLng(Double.valueOf(resultNodeList.item(0).getTextContent()));
			    
			    leg.setMainStartLocation(coord);
			    
			    coord = new Coord();
			    
			    resultNodeList = (NodeList) xpath.evaluate("//leg/end_location/lat", geocoderResultDocument, XPathConstants.NODESET);
			    coord.setLat(Double.valueOf(resultNodeList.item(0).getTextContent()));
			    
			    resultNodeList = (NodeList) xpath.evaluate("//leg/end_location/lng", geocoderResultDocument, XPathConstants.NODESET);
			    coord.setLng(Double.valueOf(resultNodeList.item(0).getTextContent()));
			    
			    leg.setMainEndLocation(coord);
			    
			    resultNodeList = (NodeList) xpath.evaluate("//leg/start_address", geocoderResultDocument, XPathConstants.NODESET);
			    leg.setMainStart_address(resultNodeList.item(0).getTextContent());
			    
			    resultNodeList = (NodeList) xpath.evaluate("//leg/end_address", geocoderResultDocument, XPathConstants.NODESET);
			    leg.setMainEnd_address(resultNodeList.item(0).getTextContent());
			    		
			    		
			    route.setLeg(leg);
			    
			    resultNodeList = (NodeList) xpath.evaluate("//overview_polyline/points", geocoderResultDocument, XPathConstants.NODESET);
			    route.setOverview_Polyline(new Overview_Polyline(resultNodeList.item(0).getTextContent()));
			    
			    Bounds bounds = new Bounds();
			    Double lat = null;
			    Double lng = null;
			    
			    resultNodeList = (NodeList) xpath.evaluate("//bounds/southwest/lat", geocoderResultDocument, XPathConstants.NODESET);			    
			    lat = Double.valueOf(resultNodeList.item(0).getTextContent());
			    
			    resultNodeList = (NodeList) xpath.evaluate("//bounds/southwest/lng", geocoderResultDocument, XPathConstants.NODESET);			    
			    lng = Double.valueOf(resultNodeList.item(0).getTextContent());

			    bounds.setSouthwest(new Coord(lat, lng));
			    
			    resultNodeList = (NodeList) xpath.evaluate("//bounds/northeast/lat", geocoderResultDocument, XPathConstants.NODESET);			    
			    lat = Double.valueOf(resultNodeList.item(0).getTextContent());
			    
			    resultNodeList = (NodeList) xpath.evaluate("//bounds/northeast/lng", geocoderResultDocument, XPathConstants.NODESET);			    
			    lng = Double.valueOf(resultNodeList.item(0).getTextContent());

			    bounds.setNortheast(new Coord(lat, lng));
			    
			    route.setBounds(bounds);
			    
			}
			else if(status_code.equals("ZERO_RESULTS")) {
				throw new ZERO_RESULTS_Exception(ZERO_RESULTS_Exception.defaultMessage);
			}
			else if(status_code.equals("REQUEST_DENIED")){
				throw new REQUEST_DENIED_Exception(REQUEST_DENIED_Exception.defaultMessage);
			}
			else if(status_code.equals("OVER_QUERY_LIMIT")){
				throw new OVER_QUERY_LIMIT_Exception(OVER_QUERY_LIMIT_Exception.defaultMessage);
			}
			
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (MalformedURLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SAXException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ParserConfigurationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (XPathExpressionException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ZERO_RESULTS_Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (REQUEST_DENIED_Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (OVER_QUERY_LIMIT_Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return route;
		
	}

		
}
